#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <cstring>
#include <ESP8266WebServer.h>

// 替换为您的WiFi SSID和密码
//const char* ssid = "YK_DYNAMIC";
//const char* password = "yk123456";
const char* ssid = "XIXI";
const char* password = "XX123456..";

const char* ssid = "";
const char* password = "";

const char* esp_ssid = "XXESP01_RELAY";  // 热点名称
const char* esp_password = "12345678";   // 热点密码

// 替换为您的MQTT代理地址和端口
const char* mqttServer = "8.137.99.64";
const int mqttPort = 1883;

// 替换为您的MQTT用户名和密码（如果需要）
const char* mqttUser = "zhaonx";
const char* mqttPassword = "Zhaonx123..";

ESP8266WebServer server(80);
WiFiClient espClient;
PubSubClient client(espClient);

// MQTT主题
const String topic_public = "XX/PUBLIC";
const String topic_heart = "XX/PUBLIC/HEART";
const String topic_answer = "XX/PUBLIC/ANSWER";
const String topic_work = "XX/RELAY/SWITCH";

// mac地址
String macAddress = "";

#define PWM1 25 // 左前电机 PWM
#define PWM2 26 // 右前电机 PWM
#define PWM3 27 // 左后电机 PWM
#define PWM4 14 // 右后电机 PWM

#define IN1 32
#define IN2 33
#define IN3 34
#define IN4 35
#define IN5 36
#define IN6 39
#define IN7 23
#define IN8 22


// 连接到WiFi
int isNull(const char* str) {
  if (str != nullptr && str[0] == '\0') {
    return 1;
  } else if (str == nullptr) {
    return 1;
  } else {
    return 0;
  }
}

// DEBUG LOG
#define DEBUG 1
void print_char(const char* str) {
  if (DEBUG) {
    Serial.println(str);
  }
}
void print_int(int num) {
  if (DEBUG) {
    Serial.println(num);
  }
}

// 连接到WiFi
void setupWiFi() {
  if (isNull(ssid) == 1 || isNull(password) == 1) {
    print_char("start softAP and HTTP server");
    WiFi.softAP(esp_ssid);  // 启动ap
    server.on("/", handleRoot);
    server.on("/connect", handleConnect);
    server.begin();  // 启动http服务
  } else {
    WiFi.begin(ssid, password);
    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 10) {
      delay(1000);
      print_char(".");
      attempts++;
    }
    if (WiFi.status() == WL_CONNECTED) {
      print_char("\nConnected to WiFi!");
      macAddress = WiFi.macAddress();
      server.send(200, "text/plain", "RELAY/" + macAddress);
      delay(1000);
      server.stop();                // 停止 HTTP 服务器
      WiFi.softAPdisconnect(true);  // 断开 AP 热点
    } else {
      print_char("\nFailed to connect. Restarting hotspot...");
      WiFi.softAP(esp_ssid);  // 重新打开热点
      server.send(500, "text/plain", "Failed to connect. Hotspot restarted.");
    }
  }
}

void handleRoot() {
  String message = "Send your WiFi credentials in the URL format: /connect?ssid=<SSID>&password=<PASSWORD>";
  server.send(200, "text/plain", message);
}

void handleConnect() {
  if (server.hasArg("ssid") && server.hasArg("password")) {
    ssid = server.arg("ssid").c_str();
    password = server.arg("password").c_str();
    setupWiFi();
  } else {
    server.send(400, "text/plain", "Missing parameters");
  }
}

void sendMessage(const char*topic,const char*message) {
  client.publish(topic, message);
}

// 发送心跳
void sendHeartBeat() {
  String fullString = "HEART/RELAY/" + macAddress;
  sendMessage(topic_heart.c_str(),fullString.c_str());
  print_char("heartBeat");
  print_char(fullString.c_str());
}

// 连接到MQTT代理
void reconnect() {
  while (!client.connected()) {
    print_char("Attempting MQTT connection...");
    if (client.connect("ESP8266Client", mqttUser, mqttPassword)) {
      print_char("MQTT connected");
      // 订阅公共消息
      client.subscribe(topic_public.c_str());
      // 订阅工作消息  topic_work +mac
      char fullString[40];  // 17 个字符 + 1 个结束符
      snprintf(fullString, sizeof(fullString), "%s/%s", topic_work.c_str(), macAddress.c_str());
      client.subscribe(fullString);
    } else {
      print_char("failed, rc=");
      print_int(client.state());
      print_char(" try again in 5 seconds");
      delay(5000);
    }
  }
}

// 处理接收到的消息
void callback(char* topic, byte* payload, unsigned int length) {

  // 协议
  String topic_type = "";
  for (int i = 0; i < strlen(topic); i++) {
    topic_type += (char)topic[i];
  }
  // 消息
  String message = "";
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }

  print_char(topic_type.c_str());
  print_char(message.c_str());

  if (topic_type.equals(topic_public)) {
    if (message.equals("SEARCH")) {  // 发送心跳
      sendHeartBeat();
    }
  } else {
    //判断接收到的消息是否为 "ON" 或 "OFF"
    if (message.equals("ON")) {
      digitalWrite(LED_PIN, LOW);
      digitalWrite(RELAY_PIN, HIGH);
      String fullString = "ON/"+macAddress;
      sendMessage(topic_answer.c_str(),fullString.c_str());
    } else if (message.equals("OFF")) {
      digitalWrite(LED_PIN, HIGH);  // 关闭 LED
      digitalWrite(RELAY_PIN, LOW);
      String fullString = "OFF/"+macAddress;
      sendMessage(topic_answer.c_str(),fullString.c_str());
    } else {
      print_char("Unknown command");
    }
  }
}

void setup() {
  Serial.begin(115200);

 // 设置 PWM 引脚为输出
  pinMode(PWM1, OUTPUT);
  pinMode(PWM2, OUTPUT);
  pinMode(PWM3, OUTPUT);
  pinMode(PWM4, OUTPUT);

  // 设置方向引脚为输出
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(IN5, OUTPUT);
  pinMode(IN6, OUTPUT);
  pinMode(IN7, OUTPUT);
  pinMode(IN8, OUTPUT);



  setupWiFi();                             // 配网
  client.setServer(mqttServer, mqttPort);  // 设置MQTT服务
  client.setCallback(callback);
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {  // 已连接
    //int led_pin_state = digitalRead(LED_PIN);
    //print(led_pin_state);
    //int relay_pin_state = digitalRead(RELAY_PIN);
    //print(relay_pin_state);
    if (!client.connected()) {
      reconnect();
    }
    client.loop();
  } else {                  // 配网
    server.handleClient();  // 处理客户端请求
  }
}

// 前进
void moveForward(int speed) {
  analogWrite(PWM1, speed);
  analogWrite(PWM2, speed);
  analogWrite(PWM3, speed);
  analogWrite(PWM4, speed);
  
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  digitalWrite(IN5, HIGH);
  digitalWrite(IN6, LOW);
  digitalWrite(IN7, HIGH);
  digitalWrite(IN8, LOW);
}

// 后退
void moveBackward(int speed) {
  analogWrite(PWM1, speed);
  analogWrite(PWM2, speed);
  analogWrite(PWM3, speed);
  analogWrite(PWM4, speed);
  
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  digitalWrite(IN5, LOW);
  digitalWrite(IN6, HIGH);
  digitalWrite(IN7, LOW);
  digitalWrite(IN8, HIGH);
}

// 左转
void turnLeft(int speed) {
  analogWrite(PWM1, speed);
  analogWrite(PWM2, speed);
  analogWrite(PWM3, 0); // 停止左后电机
  analogWrite(PWM4, 0); // 停止右后电机
  
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  digitalWrite(IN5, LOW); // 停止左后电机
  digitalWrite(IN6, LOW);
  digitalWrite(IN7, LOW); // 停止右后电机
  digitalWrite(IN8, LOW);
}

// 右转
void turnRight(int speed) {
  analogWrite(PWM1, speed);
  analogWrite(PWM2, speed);
  analogWrite(PWM3, 0); // 停止左后电机
  analogWrite(PWM4, 0); // 停止右后电机
  
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  digitalWrite(IN5, LOW); // 停止左后电机
  digitalWrite(IN6, LOW);
  digitalWrite(IN7, LOW); // 停止右后电机
  digitalWrite(IN8, LOW);
}

// 停止电机
void stopMotors() {
  analogWrite(PWM1, 0);
  analogWrite(PWM2, 0);
  analogWrite(PWM3, 0);
  analogWrite(PWM4, 0);
}
